package com.dhcc.bpm.modules.orga.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.dhcc.bpm.common.annotation.Log;
import com.dhcc.bpm.common.config.AppEmailConfig;
import com.dhcc.bpm.common.enums.BusinessType;
import com.dhcc.bpm.common.enums.ConfigType;
import com.dhcc.bpm.common.json.JSONObject;
import com.dhcc.bpm.common.redisMessage.RedisMessageSender;
import com.dhcc.bpm.common.sm.SM2Utils;
import com.dhcc.bpm.common.utils.*;
import com.dhcc.bpm.modules.api.service.IApiService;
import com.dhcc.bpm.modules.api.service.IBaseProductService;
import com.dhcc.bpm.modules.api.service.IProductService;
import com.dhcc.bpm.modules.api.vo.ApiListVo;
import com.dhcc.bpm.modules.api.vo.ApiVO;
import com.dhcc.bpm.modules.api.vo.ProductVO;
import com.dhcc.bpm.modules.common.entity.Plupload;
import com.dhcc.bpm.modules.common.entity.Upload;
import com.dhcc.bpm.modules.common.service.IPluploadService;
import com.dhcc.bpm.modules.log.service.IGatewayLogDayService;
import com.dhcc.bpm.modules.log.vo.AppApiViewVo;
import com.dhcc.bpm.modules.log.vo.AppRankVo;
import com.dhcc.bpm.modules.orga.entity.App;
import com.dhcc.bpm.modules.orga.entity.AppApi;
import com.dhcc.bpm.modules.orga.entity.Orga;
import com.dhcc.bpm.modules.orga.entity.TestApply;
import com.dhcc.bpm.modules.orga.service.IAppApiService;
import com.dhcc.bpm.modules.orga.service.IAppService;
import com.dhcc.bpm.modules.orga.service.IOrgaService;
import com.dhcc.bpm.modules.orga.service.ITestApplyService;
import com.dhcc.bpm.modules.orga.vo.*;
import com.dhcc.bpm.modules.sandbox.service.ISandboxCaseService;
import com.dhcc.bpm.modules.system.entity.Dict;
import com.dhcc.bpm.modules.system.service.IDictService;
import com.dhcc.bpm.modules.workflow.dto.ProcessStartDto;
import com.dhcc.bpm.modules.workflow.service.IWorkFlowService;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.log.annotation.ApiLog;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.utils.Func;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName AppController
 * @Description 应用/渠道信息 控制器
 * @Author daina
 * @Date 2020/2/24 19:25
 * @Version V1.0
 * @Copyright: 2020 东华软件 . All rights reserved.
 */
@RestController
@AllArgsConstructor
@NoArgsConstructor
@RequestMapping("bpm-orga/app")
@Api(value = "应用/渠道信息", tags = "应用/渠道信息接口")
public class AppController extends BladeController {
    private static final Logger log = LoggerFactory.getLogger(AppController.class);
    @Autowired
    private AppEmailConfig appEmailConfig;
    @Autowired
    private IApiService apiService;
    @Autowired
    private EmailUtils emailUtils;
    @Autowired
    private IPluploadService pluploadService;

    @Autowired
    private IOrgaService orgaService;
    @Autowired
    private IAppService appService;
    @Autowired
    private RedisMessageSender redisMessageSender;
    @Autowired
    private IAppApiService appApiService;
    @Autowired
    private IDictService dictService;
    @Autowired
    private TokenStore tokenStore;
    @Autowired
    private IWorkFlowService iWorkFlowService;

    @Autowired
    private ITestApplyService testApplyService;

    @Autowired
    private IGatewayLogDayService gatewayLogDayService;

    @Autowired
    private IBaseProductService baseProductService;
    @Autowired
    private SendSMSUtils sendSMSUtils;

    @Autowired
    private ISandboxCaseService iSandboxCaseService;
    @Autowired
    private IProductService productService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Value("${bpm.approval.isSendMail}")
    private boolean isSendFlag;
    @Value("${bpm.sms.msgContent}")
    private String msgContent;
    @Value("${bpm.approval.isApprovalApp}")
    private boolean isApprovalApp;

    @GetMapping("/listApiByAppId")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "分页", notes = "传入appApi")
    @ApiLog("应用API关系表 分页")
    @Log(title = "应用API关系表 分页", businessType = BusinessType.SELECT)
    public R<IPage<AppApiVO>> listApiByAppId(AppApiVO appApi, Query query) {
        IPage<AppApiVO> pages = appApiService.listApiByAppId(Condition.getPage(query), appApi);
        return R.data(pages);
    }

    /**
     * @param app
     * @return org.springblade.core.tool.api.R<com.dhcc.bpm.modules.orga.vo.AppDetailVo>
     * @Description 详情
     * @Author daina
     * @Date 10:38 2020/2/25
     **/
    @GetMapping("/detail")
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "详情", notes = "传入app")
    @ApiLog("应用/渠道信息 详情")
    @Log(title = "应用/渠道信息 详情", businessType = BusinessType.SELECT)
    public R<AppDetailVo> detail(App app) {
        AppVO appVO = new AppVO();
        App appDeatil = null;
        AppDetailVo appDetailVo = new AppDetailVo();
        if (app != null) {
            appDeatil = appService.getOne(Condition.getQueryWrapper(app));
            if (appDeatil != null) {
                List<AppApiVO> appApiList = appApiService.findApiList(appDeatil, "2");
                TestApply tApply = new TestApply();
                tApply.setAppId(appDeatil.getId());
                TestApply tApplyDetail = testApplyService.getOne(Condition.getQueryWrapper(tApply));
                if (appDeatil != null && tApplyDetail != null) {
                    BeanUtils.copyProperties(appDeatil, appVO);
                    appVO.setTestApplyId(String.valueOf(tApplyDetail.getId()));
                    appVO.setTestBeginTime(tApplyDetail.getTestBeginTime());
                    appVO.setTestEndTime(tApplyDetail.getTestEndTime());
                    appVO.setApplyMsg(tApplyDetail.getApplyMsg());
                }

                // 统计api 信息  (响应次数、响应成功率、响应时间)
                if (appApiList != null && appApiList.size() > 0) {
                    for (AppApiVO appApiVO : appApiList) {
                        AppApiViewVo appApiViewVo = new AppApiViewVo();
                        appApiViewVo.setApiId(appApiVO.getApiCode());
                        appApiViewVo.setAppId(appApiVO.getAppCode());
                        appApiViewVo.setEnv("0"); // 环境标志  0-生产环境
                        AppApiViewVo apiCountData = gatewayLogDayService.apiCount(appApiViewVo);
                        if (apiCountData != null) {
                            DecimalFormat df = new DecimalFormat("0.00");//格式化小数
                            // 求成功率
                            String successRateStr = "0.00%";
                            double successRate = 0;
                            if (apiCountData.getRequestNum() != 0) {
                                successRate = (double) apiCountData.getSuccessNum() / apiCountData.getRequestNum() * 100;//返回的是String类型
                                successRateStr = df.format(successRate) + "%";
                            }

                            // 平均响应时间
                            double avgResTime = 0.00;
                            if (apiCountData.getLineNum() != 0) {
                                avgResTime = Double.valueOf(df.format(apiCountData.getResponseTime() / apiCountData.getLineNum()));
                            }

                            appApiVO.setNum(apiCountData.getRequestNum());
                            appApiVO.setSuccessNum(apiCountData.getSuccessNum());
                            appApiVO.setSuccessRate(successRateStr);
                            appApiVO.setResponseTime(avgResTime);
                            appApiVO.setApiLinkName("API名称");
                        }
                    }
                }
                appDetailVo.setApiList(appApiList);
            }
        }

        appDetailVo.setApp(appDeatil);
        appDetailVo.setAppVo(appVO);
        return R.data(appDetailVo);
    }

    /**
     * @param token
     * @return org.springframework.security.oauth2.provider.OAuth2Authentication
     * @Description 查看token详情
     * @Author daina
     * @Date 9:51 2020/4/16
     **/
    @GetMapping("/tokenDetail")
    public R<TokenDetailVo> tokenDetail(String token) {
        OAuth2Authentication authentication = tokenStore.readAuthentication(token);
        if (authentication == null) {
            return R.data(null);
        }
        OAuth2Request oAuth2Request = authentication.getOAuth2Request();
        List<String> list = new ArrayList<>();
        oAuth2Request.getAuthorities().stream().forEach(auth -> list.add(((GrantedAuthority) auth).getAuthority()));
        log.info("" + list);
        String apiNames = "";
        if (list.size() > 0) {
            for (String apiCode : list) {
                ApiListVo apiListVo = apiService.selectByApiCode(apiCode);
                if (apiListVo != null) {
                    apiNames = apiNames + "," + apiListVo.getApiName();
                }
            }
            if (!apiNames.equals("")) {
                apiNames = apiNames.substring(0, apiNames.length() - 1);
            }
        }
        TokenDetailVo detail = new TokenDetailVo();
        detail.setAuthorities(apiNames);
        Iterator<String> it = oAuth2Request.getScope().iterator();
        String scope = "";
        while (it.hasNext()) {
            String str = it.next();
            log.info(scope + str);
            scope = scope + str + ",";
        }
        if (!scope.equals("")) {
            scope = scope.substring(0, scope.length() - 1);
        }
        detail.setScope(scope);
        detail.setClientId(oAuth2Request.getClientId());
        detail.setExtensions(oAuth2Request.getExtensions());
        detail.setGrantType(oAuth2Request.getGrantType());
        detail.setRedirectUri(oAuth2Request.getRedirectUri());
        detail.setResponseTypes(oAuth2Request.getResponseTypes());
        detail.setRequestParameters(oAuth2Request.getRequestParameters());
        return R.data(detail);
    }

    /**
     * @param app
     * @return org.springblade.core.tool.api.R<com.dhcc.bpm.modules.orga.entity.App>
     * @Description 查询app详情
     * @Author sjm
     * @Date 16:12 2020/3/14 0014
     **/
    @GetMapping("/appDetail")
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "详情", notes = "传入app")
    @ApiLog("应用/渠道信息 详情")
    @Log(title = "应用/渠道信息 详情", businessType = BusinessType.SELECT)
    public R<App> appDetail(App app) {
        App detail = appService.getById(app.getId());
        return R.data(detail);
    }

    /**
     * @param appRankVo
     * @param query
     * @return org.springblade.core.tool.api.R<com.baomidou.mybatisplus.core.metadata.IPage < com.dhcc.bpm.modules.orga.entity.App>>
     * @Description 分页 应用/渠道信息 默认operation_type=1 操作类型：接入
     * @Author daina
     * @Date 10:38 2020/2/25
     **/
    @GetMapping("/list")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "分页", notes = "传入app")
    @ApiLog("应用/渠道信息 分页")
    @Log(title = "应用/渠道信息 分页", businessType = BusinessType.SELECT)
    public R<IPage<AppRankVo>> list(AppRankVo appRankVo, Query query) {
        AppRankVo appRankVo2 = new AppRankVo();
        BeanUtils.copyProperties(appRankVo, appRankVo2);
        if (appRankVo.getProductId() != null) {
            //应用产品页面传进来的id去统计页面，应用产品和api是多对多关系，找到api的id，在找到渠道id
            //1.通过ProductId查出所有apiId，再通过apiId查对应的所有OPC_APP_ID
            AppVO appVO = new AppVO();
            appVO.setOpcProductId(Long.valueOf(appRankVo.getProductId()));
            List<AppVO> appList = appService.getAppList(appVO);
            appList.removeAll(Collections.singleton(null));
            if (appList.size() > 0 && null == appList.get(0)) {
                //没有匹配的订阅渠道
                R r = new R();
                r.setMsg("没有匹配的订阅渠道");
                r.setCode(200);
                r.setData(null);
                return r;
            }
            Long[] ids = new Long[appList.size()];
            for (int i = 0; i < appList.size(); i++) {
                ids[i] = Long.valueOf(appList.get(i).getOpcAppId());
            }
            appRankVo2.setAppIds(ids);
        } else if (appRankVo.getApiId() != null) {
            //2.api发布页面进来查询
//			OPC_APP_ID表通过apiId查对应的所有OPC_APP_ID去重
            AppVO appVO = new AppVO();
            appVO.setOpcApiId(appRankVo.getApiId());
            List<AppVO> appList = appService.getAppList(appVO);
            appList.removeAll(Collections.singleton(null));
            if (appList.size() == 0) {
                //没有匹配的订阅渠道
                R r = new R();
                r.setMsg("没有匹配的订阅渠道");
                r.setCode(200);
                r.setData(null);
                return r;
            }
            Long[] ids = new Long[appList.size()];
            for (int i = 0; i < appList.size(); i++) {
                ids[i] = Long.valueOf(appList.get(i).getOpcAppId());
            }
            appRankVo2.setAppIds(ids);
        } else if (appRankVo.getBaseProductId() != null) {
            //3.基础产品页面传进来
            AppVO appVO = new AppVO();
            appVO.setBaseProductId(appRankVo.getBaseProductId());
            List<AppVO> appList = appService.getAppListByBasePro(appVO);
            if (appList.size() == 1 && null == appList.get(0)) {
                //没有匹配的订阅渠道
                R r = new R();
                r.setMsg("没有匹配的订阅渠道");
                r.setCode(200);
                r.setData(null);
                return r;
            }
            Long[] ids = new Long[appList.size()];
            for (int i = 0; i < appList.size(); i++) {
                if (null != appList.get(i)) {
                    ids[i] = Long.valueOf(appList.get(i).getOpcAppId());
                }
            }
            appRankVo2.setAppIds(ids);
        } else if (appRankVo.getOpcSysId() != null) {
            //4.系统页面传进来----系统id，找到基础产品id，在找到api的id，在找到渠道id
            AppVO appVO = new AppVO();
            appVO.setOpcSysId(appRankVo.getOpcSysId());
            List<AppVO> appList = appService.getAppListBySysId(appVO);
            if (appList.size() == 1 && null == appList.get(0)) {
                //没有匹配的订阅渠道
                R r = new R();
                r.setMsg("没有匹配的订阅渠道");
                r.setCode(200);
                r.setData(null);
                return r;
            }
            Long[] ids = new Long[appList.size()];
            for (int i = 0; i < appList.size(); i++) {
                if (null != appList.get(i)) {
                    ids[i] = Long.valueOf(appList.get(i).getOpcAppId());
                }
            }
            appRankVo2.setAppIds(ids);
        }
//		if (appRankVo2.getAppIds().length==0){
//			//没有匹配的订阅渠道
//			R r=new R();
//			r.setMsg("没有匹配的订阅渠道");
//			r.setCode(200);
//			r.setData(null);
//			return r;
//		}

        appRankVo2.setEnvStr("0"); // 环境标志  0-生产环境
        IPage<AppRankVo> pages = gatewayLogDayService.countAppNum(Condition.getPage(query), appRankVo2);
        if (pages.getRecords() != null && pages.getRecords().size() > 0) {
            for (AppRankVo appRank : pages.getRecords()) {
                DecimalFormat df = new DecimalFormat("0.00");//格式化小数
                //成功率
                double successRate = 0.00;
                if (appRank.getNum() != 0) {
                    successRate = Double.valueOf(df.format((double) appRank.getSuccessNum() / appRank.getNum() * 100));//返回的是String类型
                }

                // 平均响应时间
                double avgResTime = 0.00;
                if (appRank.getLineNum() != 0) {
                    avgResTime = Double.valueOf(df.format(appRank.getResponseTime() / appRank.getLineNum()));
                }

                appRank.setSuccessRate(successRate + "%");
                appRank.setResponseTime(avgResTime);
                //赋值联系方式
                if (!("").equals(appRank.getPrpTel())) {
                    appRank.setContactInfo(appRank.getPrpTel());
                } else {
                    appRank.setContactInfo(appRank.getPrpEmail());
                }
                appRank.setChangeNum(appService.changeNum(appRank.getId()));
            }
        }
        return R.data(pages);
    }


    /**
     * @param app
     * @param bladeUser
     * @return org.springblade.core.tool.api.R<java.util.List < com.dhcc.bpm.modules.orga.entity.App>>
     * @Description 下拉渠道
     * @Author daina
     * @Date 10:38 2020/2/25
     **/
    @GetMapping("/select")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "下拉渠道名称", notes = "传入app")
    @ApiLog("下拉渠道名称")
    @Log(title = "下拉渠道名称", businessType = BusinessType.SELECT)
    public R<List<App>> select(App app, BladeUser bladeUser) {
        QueryWrapper<App> queryWrapper = Condition.getQueryWrapper(app);
        List<App> list = appService.list((!bladeUser.getTenantId().equals(BladeConstant.ADMIN_TENANT_ID)) ? queryWrapper.lambda().eq(App::getTenantId, bladeUser.getTenantId()) : queryWrapper);
        return R.data(list);
    }

    /**
     * @param app
     * @param query
     * @return org.springblade.core.tool.api.R<com.baomidou.mybatisplus.core.metadata.IPage < com.dhcc.bpm.modules.orga.vo.AppVO>>
     * @Description 自定义分页 应用/渠道信息
     * @Author daina
     * @Date 10:38 2020/2/25
     **/
    @GetMapping("/page")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "分页", notes = "传入app")
    @ApiLog("应用/渠道信息 分页")
    @Log(title = "应用/渠道信息 分页", businessType = BusinessType.SELECT)
    public R<IPage<AppVO>> page(AppVO app, Query query) {
        IPage<AppVO> pages = appService.selectAppPage(Condition.getPage(query), app);
        return R.data(pages);
    }

    /**
     * @param app
     * @param query
     * @return org.springblade.core.tool.api.R<com.baomidou.mybatisplus.core.metadata.IPage < com.dhcc.bpm.modules.orga.vo.AppVO>>
     * @Description 认证管理查询app
     * @Author daina
     * @Date 18:04 2020/3/21
     **/
    @GetMapping("/listApp")
    @ApiLog("认证管理查询app")
    @Log(title = "认证管理查询app", businessType = BusinessType.SELECT)
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "认证管理查询app", notes = "传入app")
    public R<IPage<AppVO>> listApp(AppVO app, Query query) {
        IPage<AppVO> pages = appService.listApp(Condition.getPage(query), app);
        return R.data(pages);
    }

    /**
     * @param app
     * @param query
     * @return org.springblade.core.tool.api.R<com.baomidou.mybatisplus.core.metadata.IPage < com.dhcc.bpm.modules.orga.vo.AppVO>>
     * @Description 查询应用变更信息
     * @Author sjm
     * @Date 14:22 2020/2/25 0025
     **/
    @GetMapping("/changeList")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "分页", notes = "传入app")
    @ApiLog("应用/渠道信息 分页")
    @Log(title = "应用/渠道信息 分页", businessType = BusinessType.SELECT)
    public R<IPage<AppVO>> changeList(AppVO app, Query query) {
        IPage<AppVO> pages = appService.changeList(Condition.getPage(query), app);
        if (pages.getRecords() != null && pages.getRecords().size() > 0) {
            for (AppVO apps : pages.getRecords()) {
                //赋值联系方式
                if (!("").equals(apps.getPrpTel())) {
                    apps.setContactInfo(apps.getPrpTel());
                } else {
                    apps.setContactInfo(apps.getPrpEmail());
                }
            }
        }
        return R.data(pages);
    }

    /**
     * @param app
     * @param query
     * @return org.springblade.core.tool.api.R<com.baomidou.mybatisplus.core.metadata.IPage < com.dhcc.bpm.modules.orga.vo.AppVO>>
     * @Description 自定义分页 应用/渠道信息
     * @Author daina
     * @Date 10:38 2020/2/25
     **/
    @GetMapping("/selectAppFlow")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "分页", notes = "传入app")
    @ApiLog("应用/渠道信息 分页")
    @Log(title = "应用/渠道信息 分页", businessType = BusinessType.SELECT)
    public R<IPage<AppVO>> selectAppFlow(AppVO app, Query query) {
        IPage<AppVO> pages = appService.selectAppFlow(Condition.getPage(query), app);
        return R.data(pages);
    }

    /**
     * @param app
     * @return org.springblade.core.tool.api.R
     * @Description 新增 应用/渠道信息
     * @Author daina
     * @Date 10:39 2020/2/25
     **/
    @PostMapping("/save")
    @ApiOperationSupport(order = 4)
    @ApiOperation(value = "新增", notes = "传入app")
    @ApiLog("应用/渠道信息 新增")
    @Log(title = "新增应用/渠道信息", businessType = BusinessType.INSERT)
    public R save(@Valid @RequestBody App app) {
        return R.status(appService.save(app));
    }

    /**
     * @param app
     * @return org.springblade.core.tool.api.R
     * @Description 修改 应用/渠道信息
     * @Author daina
     * @Date 10:39 2020/2/25
     **/
    @PostMapping("/update")
    @ApiOperationSupport(order = 5)
    @ApiOperation(value = "修改", notes = "传入app")
    @ApiLog("应用/渠道信息 修改")
    @Log(title = "修改应用/渠道信息", businessType = BusinessType.UPDATE)
    public R update(@Valid @RequestBody App app) {
        app.setRefreshStatus("0");
        return R.status(appService.updateById(app));
    }

    /**
     * @param app
     * @return org.springblade.core.tool.api.R
     * @Description 新增或修改 应用/渠道信息
     * @Author daina
     * @Date 10:39 2020/2/25
     **/
    @PostMapping("/submit")
    @ApiOperationSupport(order = 6)
    @ApiOperation(value = "新增或修改", notes = "传入app")
    @ApiLog("应用/渠道信息 新增或修改")
    @Log(title = "新增应用/渠道信息", businessType = BusinessType.INSERT)
    public R submit(@Valid @RequestBody App app) {
        return R.status(appService.saveOrUpdate(app));
    }


    /**
     * @param ids
     * @return org.springblade.core.tool.api.R
     * @Description 删除 应用/渠道信息
     * @Author dainaselectCount
     * @Date 10:39 2020/2/25
     **/
    @PostMapping("/remove")
    @ApiOperationSupport(order = 7)
    @ApiOperation(value = "删除 应用/渠道信息", notes = "传入ids")
    @Log(title = "删除 应用/渠道信息", businessType = BusinessType.DELETE)
    @ApiLog("删除 应用/渠道信息")
    @Transactional(rollbackFor = Exception.class)
    public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
        String[] arrayIds = ids.split(",");
        for (String id : arrayIds) {
            List<App> list = appService.findByPId(id);
            for(App app : list){
               ids = ids + "," + app.getId();
            }
        }
        String[] arrayIds2 = ids.split(",");
        for (String id : arrayIds2) {//删除id和pid对应的工作流
            iWorkFlowService.deleteRelated("c", id);//渠道申请
            iWorkFlowService.deleteRelated("p", id);//渠道变更
        }
        if (Func.toLongList(ids).size() > 0) {
            //   删除     opc_app_api
            int delAppApi = appApiService.delAppApiByAppId(Func.toLongList(ids));
            // 查询 关联 OPC_SANDBOX_case 的id
            List<Long> caseIds = appApiService.selectAppCaseByAppIds(Func.toLongList(ids));
            if (caseIds.size() > 0) {
                int delCase = appApiService.delCaseById(caseIds);
                //	删除	OPC_SANDBOX_API 根据 case_id
                int delCaseApi = appApiService.delCaseApiByCaseIds(caseIds);
            }
            //测试环境数据删除
            testApplyService.deleteLogic(Func.toLongList(ids));
        }

        return R.status(appService.delAppIdAndPid(Func.toLongList(ids)));
    }

    /**
     * @param id
     * @param size
     * @param algorithm
     * @param keyUsage
     * @return org.springblade.core.tool.api.R
     * @Description 生成 应用/渠道公私钥信息
     * @Author daina
     * @Date 10:39 2020/2/25
     **/
    @PostMapping("/createKey")
    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "生成应用/渠道公私钥信息", notes = "传入id")
    @Log(title = "生成应用/渠道公私钥信息", businessType = BusinessType.UPLOAD)
    @ApiLog("生成应用/渠道公私钥信息")
    public R createKey(@ApiParam(value = "渠道ID", required = true) @RequestParam String id,
                       @ApiParam(value = "长度", required = true) @RequestParam String size,
                       @ApiParam(value = "算法", required = true) @RequestParam String algorithm,
                       @ApiParam(value = "环境", required = true) @RequestParam Long keyUsage,
                       @ApiParam(value = "类型", required = true) @RequestParam String type,
//                       @ApiParam(value = "有效期", required = true) @RequestParam String expire,
                       @ApiParam(value = "安全方式", required = true) @RequestParam String safeMode
    ) {
        try {
            App app = appService.getById(id);
            app.setSafeMode(safeMode);
            Map<String, Object> keyMap = null;
            Map<String, Object> keyEncrypMap = null;
            String publicKey = null;
            String privateKey = null;
            String publicEncrypKey = null;
            String privateEncrypKey = null;


            if ("publicKey".equals(type)) {

                if (algorithm.equals("SM2")) {
                    keyMap = SM2Utils.generateKeyPair();
                    privateKey = keyMap.get(SM2Utils.PRIVATE_KEY).toString();
                    publicKey = keyMap.get(SM2Utils.PUBLIC_KEY).toString();
                    app.setEncrypType(0l);
                } else {
                    keyMap = RSAKeyPairGenUtil.initKey(size, algorithm);
                    privateKey = RSAKeyPairGenUtil.getPrivateKey(keyMap);
                    publicKey = RSAKeyPairGenUtil.getPublicKey(keyMap);
                    app.setEncrypType(1l);
                }
                if (keyUsage == 1) {
                    app.setPublicKey(publicKey);
                    app.setPrivateKey(privateKey);
                } else {
                    app.setTestPublicKey(publicKey);
                    app.setTestPrivateKey(privateKey);
                }

            } else if ("publicEncrypKey".equals(type)) {

                if (algorithm.equals("SM2")) {
                    keyEncrypMap = SM2Utils.generateKeyPair();
                    privateEncrypKey = keyEncrypMap.get(SM2Utils.PRIVATE_KEY).toString();
                    publicEncrypKey = keyEncrypMap.get(SM2Utils.PUBLIC_KEY).toString();
                    app.setEncrypType(0L);
                } else {
                    keyEncrypMap = RSAKeyPairGenUtil.initKey(size, algorithm);
                    privateEncrypKey = RSAKeyPairGenUtil.getPrivateKey(keyEncrypMap);
                    publicEncrypKey = RSAKeyPairGenUtil.getPublicKey(keyEncrypMap);
                    app.setEncrypType(1L);
                }
                if (keyUsage == 1) {
                    app.setPublicEncryptKey(publicEncrypKey);
                    app.setPrivateEncryptKey(privateEncrypKey);
                } else {
                    app.setTestPublicEncryptKey(publicEncrypKey);
                    app.setTestPrivateEncryptKey(privateEncrypKey);
                }

            }else {
                if (algorithm.equals("SM2")) {
                    keyEncrypMap = SM2Utils.generateKeyPair();
                    privateEncrypKey = keyEncrypMap.get(SM2Utils.PRIVATE_KEY).toString();
                    publicEncrypKey = keyEncrypMap.get(SM2Utils.PUBLIC_KEY).toString();
                    keyMap = SM2Utils.generateKeyPair();
                    privateKey = keyMap.get(SM2Utils.PRIVATE_KEY).toString();
                    publicKey = keyMap.get(SM2Utils.PUBLIC_KEY).toString();
                    app.setEncrypType(0L);
                } else {
                    keyEncrypMap = RSAKeyPairGenUtil.initKey(size, algorithm);
                    privateEncrypKey = RSAKeyPairGenUtil.getPrivateKey(keyEncrypMap);
                    publicEncrypKey = RSAKeyPairGenUtil.getPublicKey(keyEncrypMap);
                    keyMap = RSAKeyPairGenUtil.initKey(size, algorithm);
                    privateKey = RSAKeyPairGenUtil.getPrivateKey(keyMap);
                    publicKey = RSAKeyPairGenUtil.getPublicKey(keyMap);
                    app.setEncrypType(1L);
                }
                if (keyUsage == 1) {
                    app.setPublicEncryptKey(publicEncrypKey);
                    app.setPrivateEncryptKey(privateEncrypKey);
                    app.setPublicKey(publicKey);
                    app.setPrivateKey(privateKey);
//                    app.setExpire(expire);
//                    app.setExpireDate(DateUtils.getPastDate(Integer.valueOf(expire), "YYYYMMdd"));
                } else {
                    app.setTestPublicEncryptKey(publicEncrypKey);
                    app.setTestPrivateEncryptKey(privateEncrypKey);
                    app.setTestPublicKey(publicKey);
                    app.setTestPrivateKey(privateKey);
//                    app.setTestExpire(expire);
//                    app.setTestExpireDate(DateUtils.getPastDate(Integer.valueOf(expire), "YYYYMMdd"));
                }
            }
            app.setRefreshStatus("0");
            app.setKeyUsage(keyUsage);
            app.setEnv(keyUsage);
            appService.updateById(app);
            return R.data(app);
        } catch (Exception e) {
            log.error("生成应用/渠道公私钥异常:{}", e);
            return R.status(false);
        }

    }

    /**
     * @param ids
     * @param env
     * @return org.springblade.core.tool.api.R
     * @Description 应用/渠道秘钥重置
     * @Author daina
     * @Date 10:39 2020/2/25
     **/
    @PostMapping("/resetSecret")
    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "应用/渠道秘钥重置", notes = "ids")
    @Log(title = "应用/渠道秘钥重置", businessType = BusinessType.RESET)
    @ApiLog("应用/渠道秘钥重置")
    public R resetSecret(@ApiParam(value = "主键集合", required = true) @RequestParam String ids,
                         @ApiParam(value = "主键集合", required = true) @RequestParam String env) {
        try {
            List<Long> idList = Func.toLongList(ids);
            for (Long id : idList) {
                App app = appService.getById(id);
                String appSecret = UUIDGenerator.getUUID();
                if (env.equals("1")) {
                    app.setAppSecret(appSecret);
                } else {
                    app.setTestAppSecret(appSecret);
                }
                app.setRefreshStatus("0");
                appService.updateById(app);
            }
            return R.status(true);
        } catch (Exception e) {
            log.error("重置应用/渠道秘钥异常:{}", e);
            return R.status(false);
        }

    }

    /**
     * @param
     * @return org.springblade.core.tool.api.R
     * @Description 刷新应用/渠道公私钥信息
     * @Author daina
     * @Date 10:39 2020/2/25
     **/
    @PostMapping("/refreshAppSecret")
    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "刷新应用/渠道公私钥信息")
    @Log(title = "刷新应用/渠道公私钥信息", businessType = BusinessType.REFRESH)
    @ApiLog("刷新应用/渠道公私钥信息")
    public R refreshAppSecret() {
        try {
            String message = redisMessageSender.format(ConfigType.APPSECRET.name(), "刷新应用/渠道公私钥信息");
            redisMessageSender.sendMessageToGateway("", message);
            App app = new App();
            app.setRefreshStatus("1");
            int result = appService.updateRefreshStatus(app);
            if (result >= 0) {
                return R.status(true);
            }
            return R.status(false);
        } catch (Exception e) {
            log.error("刷新应用/渠道公私钥信息失败:{}", e);
            return R.status(false);
        }
    }

    /**
     * @param
     * @return org.springblade.core.tool.api.R
     * @Description 刷新Token信息
     * @Author daina
     * @Date 10:40 2020/2/25
     **/
    @PostMapping("/refreshToken")
    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "刷新Token信息")
    @Log(title = "刷新Token信息", businessType = BusinessType.REFRESH)
    @ApiLog("刷新Token信息")
    public R refreshToken() {
        try {
            //管理端不使用redis推送刷新token  修改时间：20200927 21:03:00
//			String message = redisMessageSender.format(ConfigType.TOKEN.name(), "刷新Token信息");
//			redisMessageSender.sendMessageToGateway("", message);
            //TODO 刷新
            //
            return R.status(false);
        } catch (Exception e) {
            log.error("刷新Token信息失败:{}", e);
            return R.status(false);
        }
    }

    /**
     * @param apiId
     * @param query
     * @return org.springblade.core.tool.api.R<com.baomidou.mybatisplus.core.metadata.IPage < org.springframework.security.oauth2.common.OAuth2AccessToken>>
     * @Description 刷新token
     * @Author daina
     * @Date 10:40 2020/2/25
     **/
    @GetMapping("/findTokens")
    @ApiOperationSupport(order = 9)
    @ApiOperation(value = "查询token")
    @ApiLog("查询token")
    @Log(title = "查询token", businessType = BusinessType.SELECT)
    public R<IPage<OAuth2AccessToken>> findTokensByClientId(@ApiParam(value = "主键集合", required = true) @RequestParam String apiId, Query query) {
        List<OAuth2AccessToken> list = new ArrayList<>();
        Collection<OAuth2AccessToken> tokens = tokenStore.findTokensByClientId(apiId);
        IPage<OAuth2AccessToken> pages = Condition.getPage(query);
        list = tokens.stream().filter(p -> tokenStore.readAccessToken(p.getValue()) != null)
                .collect(
                        Collectors.collectingAndThen(
                                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(OAuth2AccessToken::getValue))), ArrayList::new));
//		if(tokens.size()>0){
//			Iterator iterator =  tokens.iterator();
//			while (iterator.hasNext()){
//				list.add((OAuth2AccessToken) iterator.next());
//			}
//			pages.setRecords(list);
//		}else{
//			pages.setRecords(null);
//		}
        pages.setRecords(list);
        pages.setTotal(list.size());
        pages.setPages(0);
        pages.setCurrent(10);
        return R.data(pages);
    }

    /**
     * @param app
     * @param bladeUser
     * @return org.springblade.core.tool.api.R<java.util.HashMap < java.lang.String, java.lang.Integer>>
     * @Description 统计应用总数以及各类别数量
     * @Author daina
     * @Date 10:40 2020/2/25
     **/
    @GetMapping("/selectCount")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "统计应用总数以及各类别数量", notes = "传入app")
    @ApiLog("统计应用总数以及各类别数量")
    @Log(title = "统计应用总数以及各类别数量", businessType = BusinessType.SELECT)
    public R<HashMap<String, Integer>> selectCount(App app, BladeUser bladeUser) {
        app.setEnv(null);
        app.setOperationType(1L);
        QueryWrapper<App> queryWrapper = Condition.getQueryWrapper(app);
        List<App> list = appService.list((!bladeUser.getTenantId().equals(BladeConstant.ADMIN_TENANT_ID)) ? queryWrapper.lambda().eq(App::getTenantId, bladeUser.getTenantId()) : queryWrapper);
        List<Dict> tree = dictService.getList("app_type");
        List<String> typeList = new ArrayList<>();
        tree.forEach(dict -> {
            if (!dict.getDictKey().equals("-1")) {
                typeList.add(dict.getDictKey());
            }
        });
        HashMap<String, Integer> hashMap = new HashMap();
        typeList.forEach(type -> {
            int count = 0;
            for (App app1 : list) {
                if (Arrays.asList(app1.getAppType().split(",")).contains(type)) {
                    count = count + 1;
                }
            }
            hashMap.put(type, count);
        });
        hashMap.put("total", list.size());
        return R.data(hashMap);
    }

    /**
     * @param app
     * @param bladeUser
     * @return org.springblade.core.tool.api.R<java.util.List < com.dhcc.bpm.modules.orga.entity.App>>
     * @Description 接入日期排序获取机构列表
     * @Author daina
     * @Date 10:40 2020/2/25
     **/
    @GetMapping("/listAll")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "接入日期排序获取机构列表", notes = "传入orga")
    @ApiLog("接入日期排序获取机构列表")
    @Log(title = "接入日期排序获取机构列表", businessType = BusinessType.SELECT)
    public R<List<App>> listAll(App app, BladeUser bladeUser) {
        QueryWrapper<App> queryWrapper = Condition.getQueryWrapper(app);
        List<App> list = appService.list((!bladeUser.getTenantId().equals(BladeConstant.ADMIN_TENANT_ID)) ? queryWrapper.lambda().eq(App::getTenantId, bladeUser.getTenantId()).orderByDesc(App::getCreateTime) : queryWrapper.lambda().orderByDesc(App::getCreateTime));
        return R.data(list);
    }

    /**
     * @param app
     * @return boolean
     * @throws
     * @Description 发送私钥邮件
     * @Author xiafayu
     * @Date 2020/2/26 9:37
     **/
    @PostMapping("/sendPrivateKeyEmail")
    @ApiOperationSupport(order = 10)
    @ApiOperation(value = "发送私钥邮件", notes = "传入app")
    @ApiLog("发送私钥邮件")
    @Log(title = "发送私钥邮件", businessType = BusinessType.SELECT)
    public boolean sendPrivateKeyEmail(App app) {
        String privateKey = "";
        String encPrivateKey = "";
        String mailTitle = appEmailConfig.getTitle();
        String encMailTitle = appEmailConfig.getTitle();
        boolean bool = false;
        if (app != null) {
            if (app.getEnv() == 0) {//生产环境
                privateKey = app.getPrivateKey();
                encPrivateKey = app.getPrivateEncryptKey();
                mailTitle += "生产环境签名私钥";
                encMailTitle += "生产环境加解密私钥";
            } else {//沙箱测试环境
                privateKey = app.getTestPrivateKey();
                encPrivateKey = app.getTestPrivateEncryptKey();
                mailTitle += "测试环境签名私钥";
                encMailTitle += "测试环境加解密私钥";
            }
            if (isSendFlag) {
                Orga orga = orgaService.getById(app.getOpcOrgaId());
                if (orga != null && orga.getOrgaEmail() != null) {
                    bool = emailUtils.sendEmail(mailTitle, orga.getOrgaEmail(), mailTitle, privateKey);
                    bool = emailUtils.sendEmail(encMailTitle, orga.getOrgaEmail(), mailTitle, encPrivateKey);
                }
            }
        }
        return bool;
    }

    /**
     * @param app
     * @return org.springblade.core.tool.api.R
     * @Description 渠道审批通过生成沙箱案例
     * @Author sjm
     * @Date 13:53 2020/3/14 0014
     **/
    @PostMapping("/createSandboxCase")
    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "生成沙箱案例", notes = "app")
    @Log(title = "生成沙箱案例", businessType = BusinessType.INSERT)
    @ApiLog("生成沙箱案例")
    public R createSandboxCase(@Valid @RequestBody AppVO app) {
        List<AppVO> list = appService.findByAppId(app.getTestAppId());
        if (list.size() > 0) {
            return R.fail(223, "该渠道号已存在，请填写新的渠道号！");
        }
        //保存修改应用审批状态以及启用状态
        app.setAppStatus("1");
        return R.status(appService.updateById(app));
//        if (appService.saveOrUpdate(app)) {
//            //保存支付账号
//            TestApply testApply = testApplyService.selectByAppId(app.getId());
//            testApply.setPayAccount(app.getPayAccount());
//            testApplyService.updateById(testApply);
//            //刷新App
//            refreshApp();
//            App byId = appService.getById(app.getId());
//            // 应用创建成功调用生成沙箱实例
//            SandboxCase sandboxCase = new SandboxCase();
//            sandboxCase.setCaseName(byId.getAppName() + "案例");
//            sandboxCase.setOpcOrgaId(byId.getOpcOrgaId());
//            sandboxCase.setOpcAppId(byId.getId());
//            iSandboxCaseService.modifySandboxCase(sandboxCase);
//            return R.status(true);
//        } else {
//            return R.status(false);
//        }

    }

    /**
     * @param
     * @return org.springblade.core.tool.api.R
     * @Description 刷新渠道
     * @Author sjm
     * @Date 14:03 2020/3/25 0025
     **/
    private R refreshApp() {
        try {
            String message = redisMessageSender.format(ConfigType.APPSECRET.name(), "刷新产品公私钥配置");
            redisMessageSender.sendMessageToGateway(null, message);
            String msg = redisMessageSender.format(ConfigType.RATELIMET.name(), "刷新产品限流配置");
            redisMessageSender.sendMessageToGateway(null, msg);
            return R.status(true);
        } catch (Exception e) {
            log.error("刷新产品配置失败:{}", e);
            return R.status(false);
        }
    }

    /**
     * @param app
     * @return org.springblade.core.tool.api.R
     * @Description 渠道启用停用
     * @Author sjm
     * @Date 13:30 2020/4/6 0006
     **/
    @PostMapping("/appChangeStatus")
    @ApiOperationSupport(order = 9)
    @ApiOperation(value = "启用停用", notes = "传入app")
    @ApiLog("应用/渠道信息 启用停用")
    @Log(title = "启用停用", businessType = BusinessType.UPDATE)
    public R appChangeStatus(@Valid @RequestBody App app) {
        //修改
        if (app.getId() != null) {
            App byId = appService.getById(app.getId());
            //启用停用刷新app
            if (app.getAppStatus() != null && !app.getAppStatus().equals(byId.getAppStatus())) {
                //刷新App
                refreshApp();
            }
        }
        return R.status(appService.updateById(app));
    }

    /**
     * @param
     * @return com.dhcc.bpm.common.json.JSONObject
     * @Description 渠道名称关联查询
     * @Author daina
     * @Date 14:40 2020/2/25
     **/
    @GetMapping("/selectByAppName")
    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "渠道名称关联查询", notes = "无参")
    @Log(title = "渠道名称关联查询", businessType = BusinessType.SELECT)
    @ApiLog("渠道名称关联查询")
    public JSONObject selectByAppName() {
        JSONObject object = new JSONObject();
        object.put("success", true);
        object.put("names", appService.selectByAppName());
        return object;
    }

    /**
     * 文件上传解析
     *
     * @param plupload
     * @param request
     * @return
     */
    @ApiLog("txt文件上传")
    @PostMapping("/fileTxtUpload")
    @Log(title = "txt文件上传", businessType = BusinessType.UPLOAD)
    public R fileTxtUpload(Plupload plupload, HttpServletRequest request) {
        Upload upload = new Upload();
        upload.setRequest(request);
        Upload uploadEntity = pluploadService.getFile(upload);
        MultipartFile file = uploadEntity.getMultipartFile();
        String result = "";
        Set<String> set = new HashSet<>();
        // ip正则表达式
        String regex = "^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\." +
                "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\." +
                "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\." +
                "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)$";
        // 数字正则表达式
        String regexNum = "^[0-9]*$";
        try {
            InputStream ins = file.getInputStream();
            try (InputStreamReader reader = new InputStreamReader(ins)) { // 建立一个输入流对象reader
                try (BufferedReader br = new BufferedReader(reader)) { // 建立一个对象，它把文件内容转成计算机能读懂的语言
                    String line = ""; // 每一行的内容
                    StringBuilder sb = new StringBuilder();
                    int lineNum = 1;
                    while ((line = br.readLine()) != null) {
//						sb.append(line).append(",");
                        line = line.trim();
                        System.out.println("ip = " + line);
                        if (line.contains("-")) {
                            String[] strArray = null;
                            strArray = line.split("-"); //拆分字符为"-" ,然后把结果交给数组strArray
                            String ipStr = "";
                            String areaStr = "";

                            System.out.println("strArray length:" + strArray.length);
                            if (strArray.length == 2) {
                                ipStr = strArray[0];
                                areaStr = strArray[1];
                                if (!ipStr.matches(regex)) {
//                                    System.out.println("ip格式错误");
                                    return R.fail("第" + lineNum + "行 ip格式错误");
                                }
                                if (!areaStr.matches(regexNum)) {
//                                    System.out.println("ip范围格式错误");
                                    return R.fail("第" + lineNum + "行 ip格式错误");
                                } else {
                                    // 截取最后一个.后面的数字
                                    int strStartIndex = ipStr.lastIndexOf(".");
                                    String ipNum = ipStr.substring(strStartIndex + 1);
                                    System.out.println("ipNum = " + ipNum);
                                    if (Integer.valueOf(areaStr) > 255 || Integer.valueOf(ipNum) >= Integer.valueOf(areaStr)) {
//                                        System.out.println("范围错误");
                                        return R.fail("第" + lineNum + "行 ip格式错误");
                                    }

                                }

                            } else {
                                return R.fail("第" + lineNum + "行 ip格式错误");
                            }
                            System.out.println("ipStr:" + ipStr);
                            System.out.println("areaStr:" + areaStr);

                        } else {
                            // 校验IP格式
                            if (!line.matches(regex)) {
                                return R.fail("第" + lineNum + "行 ip格式错误");
                            }
                        }

                        System.out.println("lineNum = " + lineNum);
                        set.add(line.toString());
                        lineNum = lineNum + 1;
                    }
                    Object[] array = set.toArray();
                    String splitSet = StringUtils.join(array);
                    System.out.println("splitSet:" + splitSet);
                    String splitSetWithComma = StringUtils.join(array, ",");
                    System.out.println("splitSetWithComma:" + splitSetWithComma);
                    result = splitSetWithComma + ",";
                    System.out.println("result:" + result);
                } catch (IOException e) {
                    log.error("读取文件异常信息;{}", e);
                }
            } catch (IOException e) {
                log.error("读取文件异常信息;{}", e);
            }
        } catch (IOException e) {
            log.error("读取文件异常信息;{}", e);
        }
        return R.data(result);
    }

    /**
     * 公私钥有效期提醒
     */
//    @Scheduled(cron = "0 0 17 * * ?")
    @Scheduled(cron = "${scheduler.expireAlarm}")
    public void sendMsg(){
         List<App> list = appService.getListByExpire(null);

        //生产环境公私钥过期
         String message = msgContent.replace("param", "生产环境");
         list.stream()
                 .filter(app -> StringUtils.isNotEmpty(app.getExpireDate()))
                 .filter(app -> StringUtils.isNotEmpty(app.getPromptTime()))
                 .forEach(app -> {
                     try {
                         String expire = DateUtils.getPastDate(Integer.valueOf(app.getPromptTime()), "yyyyMMdd");
                         if(expire.compareTo(app.getExpireDate())>=0){
                             sendSMSUtils.sendSMS(app.getPrpTel(), message);
                         }
                     } catch (Exception e) {
                         log.error("日期转换异常:{}", e);
                     }
                 });

        //生产环境公私钥过期
        String testMessage = msgContent.replace("param", "测试环境");
        list.stream()
                .filter(app -> StringUtils.isNotEmpty(app.getTestExpireDate()))
                .filter(app -> StringUtils.isNotEmpty(app.getTestPromptTime()))
                .forEach(app -> {
                    try {
                        String expire = DateUtils.getPastDate(Integer.valueOf(app.getTestPromptTime()), "yyyyMMdd");
                        if(expire.compareTo(app.getTestExpireDate())>=0){
                            sendSMSUtils.sendSMS(app.getPrpTel(), testMessage);
                        }
                    } catch (Exception e) {
                        log.error("日期转换异常:{}", e);
                    }
                });
    }


    /**
     * @param app
     * @return org.springblade.core.tool.api.R
     * @Description 创建应用/渠道信息
     * @Author daina
     * @Date 10:39 2020/2/25
     **/
    @PostMapping("/createApp")
    @ApiOperationSupport(order = 6)
    @ApiOperation(value = "创建应用", notes = "传入app")
    @ApiLog("创建应用")
    @Transactional(rollbackFor = Exception.class)
    @Log(title = "创建应用", businessType = BusinessType.INSERT)
    public R createApp(@Valid @RequestBody AppVO app) {
        Orga orga = orgaService.getById(app.getOpcOrgaId());
        if(null != orga){
            app.setOrgaName(orga.getOrgaName());
            app.setOrgaCode(orga.getOrgaCard());
        }

        //渠道默认值
        app.setStatus(0);
        app.setOperationType(1L);
        app.setIsDeleted(0);
        app.setAppStatus("0");
        app.setAuthorizedGrantTypes("client_credentials");
        app.setTestExpire(app.getExpire());
        String expireDate = DateUtils.getLastYear(Integer.valueOf(app.getExpire()), "yyyyMMdd");
        app.setExpireDate(expireDate);
        app.setTestExpireDate(expireDate);
        app.setExpSeq(stringRedisTemplate.opsForValue().get("expSeq"));

        if(!appService.save(app)){
            return R.fail("渠道创建失败");
        }

        TestApply testApply = new TestApply();
        testApply.setAppId(app.getId());
        testApply.setOrgaId(app.getOpcOrgaId());
        testApply.setApplyMsg(app.getApplyMsg());
        testApply.setApplyQps(app.getApplyQps());
        testApply.setApprovalQps(app.getApprovalQps());
        testApply.setTestBeginTime(app.getTestBeginTime());
        testApply.setTestEndTime(app.getTestEndTime());
        testApply.setStatus(0);
        testApply.setIsDeleted(0);
        testApply.setExpSeq(stringRedisTemplate.opsForValue().get("expSeq"));
        if(!testApplyService.save(testApply)){
            //回滚渠道信息
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
             return R.fail("渠道创建失败");
        }

        //渠道关联应用产品及api
        List<String> appApiList = app.getProductApiList();
        for (String appApi : appApiList){
            String [] ids = appApi.split("#");
            AppApi opcAppApi = new AppApi();
            opcAppApi.setOpcAppId(app.getId());
            opcAppApi.setOpcApiId(Long.valueOf(ids[1]));
            opcAppApi.setOpcProductId(Long.valueOf(ids[0]));
            opcAppApi.setApprovalEnv("2");
            opcAppApi.setChangeStatus("1");
            opcAppApi.setValidStatus("0");
            opcAppApi.setExpSeq(stringRedisTemplate.opsForValue().get("expSeq"));
            appApiService.save(opcAppApi);
        }

        //发起工作流审批
        if(isApprovalApp){
            ProcessStartDto processStartDto = new ProcessStartDto();
            processStartDto.setAppId("c" + app.getId());
            processStartDto.setUserId(String.valueOf(orga.getOpcUserId()));
            processStartDto.setProcessKey("channel_create");
            Map<String, Object> wfParm = new HashMap<>();
            wfParm.put("params", "");
            processStartDto.setWfParm(wfParm);
            // 调用发布流程接口
            JSONObject resJson = iWorkFlowService.start(processStartDto);
            // 发布流程成功
            if (resJson != null && resJson.getInt("code") == 200) {
               return R.success("渠道创建成功，正在审核中！");
            }

            //回滚渠道信息和测试环境信息
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

            return R.fail("渠道创建失败！");
        }else{
            //自动审批通过
            app.setStatus(1);
            testApply.setStatus(1);
            appService.saveOrUpdate(app);
            testApplyService.saveOrUpdate(testApply);
        }
        return R.success("渠道已创建");
    }

    @GetMapping("/queryProductWithApi")
    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "查询应用产品关联接口", notes = "")
    @ApiLog("查询应用产品关联接口")
    @Transactional(rollbackFor = Exception.class)
    @Log(title = "查询应用产品关联接口", businessType = BusinessType.SELECT)
    public R queryProductWithApi(){
        List<ProductVO> prdtList = productService.queryProduct();
        prdtList.forEach(product -> {
            List<ApiVO> apiList = apiService.findApiByProductId(product.getId());
            if(apiList.size() > 0){
                product.setChildren(apiList);
            }else{
                product.setChildren(null);
            }
        });
        prdtList = prdtList.stream().filter(productVO -> productVO.getChildren() != null).collect(Collectors.toList());
        return R.data(prdtList);
    }

    @GetMapping("/queryApp")
    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "渠道变更修改数据查询", notes = "app")
    @ApiLog("渠道变更修改数据查询")
    @Transactional(rollbackFor = Exception.class)
    @Log(title = "渠道变更修改数据查询", businessType = BusinessType.SELECT)
    public R queryApp(@Valid @RequestParam("id") long id){
        App app = appService.getById(id);
        TestApply testApply = testApplyService.selectByAppId(id);
        List<AppApi> appApiList = appApiService.selectByAppId(id);
        OpcAppApiVO opcAppApiVO = new OpcAppApiVO();
        opcAppApiVO.setAppApiList(appApiList);
        opcAppApiVO.setApp(app);
        opcAppApiVO.setTestApply(testApply);
        return R.data(opcAppApiVO);
    }

    /**
     * @param opcAppApiVO
     * @return org.springblade.core.tool.api.R
     * @Description 创建应用/渠道信息
     * @Author daina
     * @Date 10:39 2020/2/25
     **/
    @PostMapping("/changeApp")
    @ApiOperationSupport(order = 6)
    @ApiOperation(value = "应用变更修改", notes = "传入app")
    @ApiLog("应用变更修改")
    @Transactional(rollbackFor = Exception.class)
    @Log(title = "应用变更修改", businessType = BusinessType.UPDATE)
    public R changeApp(@Valid @RequestBody OpcAppApiVO opcAppApiVO) {
        App app = opcAppApiVO.getApp();
        TestApply testApply = opcAppApiVO.getTestApply();
        App oldApp = appService.getById(app.getId());
        List<String> productApiList = opcAppApiVO.getProductApiList();

        Orga orga = orgaService.getById(app.getOpcOrgaId());
        if(null != orga){
            app.setOrgaName(orga.getOrgaName());
            app.setOrgaCode(orga.getOrgaCard());
        }

        app.setStatus(0);
        app.setIsDeleted(0);
        app.setTestExpire(app.getExpire());
        String expireDate = DateUtils.getLastYear(Integer.valueOf(app.getExpire()), "yyyyMMdd");
        app.setExpireDate(expireDate);
        app.setTestExpireDate(expireDate);

        testApply.setStatus(0);
        testApply.setIsDeleted(0);

        Long appId = app.getId();
        //渠道变更和修改标志 0-变更 1-修改
        if ("1".equals(opcAppApiVO.getFlag()) && StringUtils.isBlank(app.getAppState())) {
            appService.updateById(app);
            testApplyService.updateById(testApply);

            // 删除产品接口列表
            appApiService.deleteByAppId(app.getId(), "2");
        } else {
            app.setId(null);
            app.setPid(appId);
            app.setAppId(oldApp.getAppId());
            app.setTestAppId(oldApp.getTestAppId());
            app.setOperationType(2L);
            app.setAuthorizedGrantTypes("0");
            app.setExpSeq(stringRedisTemplate.opsForValue().get("expSeq"));
            appService.save(app);
        }
        // 更新原数据状态未待审批
        if(null != app.getPid()){
            App oriApp = new App();
            oriApp.setId(app.getPid());
            oriApp.setAppState("0");
            appService.updateById(oriApp);
        }


        for (Object id : productApiList) {
            String productId = String.valueOf(id).split("#")[0];
            String apiId = String.valueOf(id).split("#")[1];
            String changeStatus = String.valueOf(id).split("#")[2];
            AppApi opcAppApi = new AppApi();
            opcAppApi.setOpcApiId(Long.valueOf(apiId));
            opcAppApi.setOpcAppId(app.getId());
            opcAppApi.setOpcProductId(Long.valueOf(productId));
            opcAppApi.setChangeStatus(changeStatus);
            opcAppApi.setApprovalEnv("2");
            opcAppApi.setValidStatus("0");
            opcAppApi.setExpSeq(stringRedisTemplate.opsForValue().get("expSeq"));
            if(!appApiService.save(opcAppApi)){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return R.success("渠道变更失败");
            }
        }

        //发起工作流审批
        if(isApprovalApp){
            ProcessStartDto processStartDto = new ProcessStartDto();

            processStartDto.setAppId("p" + app.getId());
            processStartDto.setProcessKey("channel_create_change");

            //渠道创建拒绝修改提交
            if("1".equals(opcAppApiVO.getFlag()) && StringUtils.isBlank(app.getAppState())){
                processStartDto.setAppId("c" + app.getId());
                processStartDto.setProcessKey("channel_create");
            }

            processStartDto.setUserId(String.valueOf(orga.getOpcUserId()));
            Map<String, Object> wfParm = new HashMap<>();
            wfParm.put("params", "");
            processStartDto.setWfParm(wfParm);
            // 调用发布流程接口
            JSONObject resJson = iWorkFlowService.start(processStartDto);
            // 发布流程成功
            if (resJson != null && resJson.getInt("code") == 200) {
                return R.success("渠道变更成功，正在审核中！");
            }

            //回滚渠道信息和测试环境信息
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

            return R.fail("渠道变更失败！");
        }else{
            //自动审批通过
            if(null != app.getPid()){
                App oriApp = new App();
                oriApp.setId(app.getPid());
                oriApp.setAppState("1");
                appService.saveOrUpdate(oriApp);
            }


            testApply.setStatus(1);
            testApplyService.saveOrUpdate(testApply);
        }

        return R.success("渠道变更成功");
    }


}
